package com.atguigu.tingshu.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.util.MongoUtil;
import com.atguigu.tingshu.model.user.UserListenProcess;
import com.atguigu.tingshu.user.service.UserListenProcessService;
import com.atguigu.tingshu.vo.album.TrackStatMqVo;
import com.atguigu.tingshu.vo.user.UserListenProcessVo;
import com.rabbitmq.tools.json.JSONUtil;
import nonapi.io.github.classgraph.json.JSONUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
@SuppressWarnings({"all"})
public class UserListenProcessServiceImpl implements UserListenProcessService {

	@Autowired
	private MongoTemplate mongoTemplate;
	@Autowired
	private RedisTemplate redisTemplate;
	@Autowired
	private RabbitService rabbitService;

	/**
	 * 根据用户ID和轨迹ID获取用户的断点时间
	 *
	 * @param userId 用户ID，用于识别特定的用户
	 * @param trackId 轨迹ID，用于识别特定的音频轨迹
	 * @return 返回用户监听过程中的断点时间，如果用户或监听过程不存在，则返回0
	 */
	@Override
	public BigDecimal getTrackBreakSecond(Long userId, Long trackId) {
	    // 创建查询条件，查找匹配轨迹ID的文档
	    Query query = Query.query(Criteria.where("trackId").is(trackId));
	    // 使用MongoDB模板执行查询，获取用户监听过程对象
	    UserListenProcess userListenProcess = mongoTemplate.findOne(query, UserListenProcess.class, MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId));

	    // 检查查询结果是否非空
	    if (null != userListenProcess) {
	        // 如果用户监听过程存在，则返回其断点时间
	        return userListenProcess.getBreakSecond();
	    }
	    // 如果用户监听过程不存在，则返回0表示没有断点时间
	    return new BigDecimal("0");
	}

	/**
	 * 更新用户播放进程
	 * 当用户收听音频时，此方法用于更新用户在特定音频轨道上的收听进程如果用户尚未开始收听该轨道，将创建新的收听进程记录
	 * 此外，如果这是用户首次收听该轨道，方法还会在Redis中设置一个键，以避免重复统计，并发送消息到消息队列，用于轨道播放统计
	 *
	 * @param userId 用户ID，用于标识用户
	 * @param userListenProcessVo 包含用户收听进程信息的视图对象，包括轨道ID和中断秒数
	 */
	@Override
	public void updateListenProcess(Long userId, UserListenProcessVo userListenProcessVo) {
	    // 根据音频ID查询用户播放进程
	    Query query = Query.query(Criteria.where("trackId").is(userListenProcessVo.getTrackId()));
	    UserListenProcess userListenProcess = mongoTemplate.findOne(query, UserListenProcess.class, MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId));

	    // 如果找到了用户播放进程，更新中断时间和更新时间
	    if (null != userListenProcess){
	        userListenProcess.setUpdateTime(new Date());
	        userListenProcess.setBreakSecond(userListenProcessVo.getBreakSecond());
	    } else {
	        // 如果没有找到用户播放进程，创建新的进程并设置初始值
	        userListenProcess = new UserListenProcess();
	        BeanUtils.copyProperties(userListenProcessVo,userListenProcess);
	        userListenProcess.setId(ObjectId.get().toString());
	        userListenProcess.setUserId(userId);
	        userListenProcess.setIsShow(1);
	        userListenProcess.setCreateTime(new Date());
	        userListenProcess.setUpdateTime(new Date());
	        // 保存新的用户播放进程到MongoDB
	        mongoTemplate.save(userListenProcess,MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId));
	    }

	    // 构造Redis键，用于记录用户是否已经开始了该轨道的收听
	    String key = "user:track:"+userId+":"+userListenProcessVo.getTrackId();
	    // 尝试在Redis中设置键，如果成功，表示这是用户首次收听该轨道
	    Boolean result = redisTemplate.opsForValue().setIfAbsent(key, "1", 1, TimeUnit.HOURS);

	    // 如果成功设置Redis键，发送消息到消息队列，用于轨道播放统计
	    if (result){
	        TrackStatMqVo trackStatMqVo = new TrackStatMqVo();
	        trackStatMqVo.setBusinessNo(UUID.randomUUID().toString().replaceAll("-",""));
	        trackStatMqVo.setAlbumId(userListenProcessVo.getAlbumId());
	        trackStatMqVo.setTrackId(userListenProcessVo.getTrackId());
	        trackStatMqVo.setStatType(SystemConstant.TRACK_STAT_PLAY);
	        trackStatMqVo.setCount(1);
	        // 发送轨道播放统计消息到RabbitMQ
	        rabbitService.sendMessage(MqConst.EXCHANGE_TRACK,MqConst.ROUTING_TRACK_STAT_UPDATE, JSON.toJSONString(trackStatMqVo));
	    }
	}

	/**
	 * 根据用户ID获取最近的播放记录
	 *
	 * @param userId 用户ID，用于查询最近的播放记录
	 * @return 返回包含专辑ID和曲目ID的Map对象，如果找不到最近的播放记录则返回null
	 */
	@Override
	public Map<String, Object> getLatelyTrack(Long userId) {
	    // 创建查询对象，用于查询最近的播放记录
	    Query query = new Query();
	    // 设置查询条件，按更新时间降序排列，并限制结果数量为1
	    query.with(Sort.by(Sort.Direction.DESC,"updateTime")).limit(1);

	    // 使用mongoTemplate执行查询，获取最近的播放记录
	    UserListenProcess userListenProcess = mongoTemplate.findOne(query, UserListenProcess.class, MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId));

	    // 判断查询结果是否为空
	    if (null !=userListenProcess){
	        // 创建Map对象，用于存储播放记录中的专辑ID和曲目ID
	        HashMap<String, Object> map = new HashMap<>();
	        // 将专辑ID和曲目ID存入Map对象中
	        map.put("albumId",userListenProcess.getAlbumId());
	        map.put("trackId",userListenProcess.getTrackId());
	        // 返回包含播放记录信息的Map对象
	        return map;
	    }
	    // 如果查询结果为空，返回null
	    return null;
	}
}
